#include <iostream>
#include <string>
#include <memory>
#include <chrono>

// gRPC 和 Protobuf
#include <grpc++/grpc++.h>
#include "protos/file_service.grpc.pb.h"
#include "protos/user_service.grpc.pb.h" // 需要用到 UserInfo 等

// Consul 服务注册
#include <ppconsul/agent.h>

// Workflow 定时器
#include "workflow/WFFacilities.h"

// 共享的核心逻辑
#include "common/config.hpp"
#include "database/db_connection.hpp"
#include "database/file_dao.hpp"
#include "database/user_dao.hpp"
#include "models/user.hpp"
#include "utils/token.hpp"

using namespace cloud::storage;

ppconsul::agent::Agent* g_consul_agent = nullptr;
std::string g_service_id = "file-service-instance-1";

// 心跳回调函数
void heartbeat_callback(WFTimerTask *task) {
    if (g_consul_agent) {
        try {
            // 直接使用全局的 agent 对象
            g_consul_agent->servicePass(g_service_id);
        } catch (const std::exception& e) {
            fprintf(stderr, "[Heartbeat] ERROR for UserService: %s\n", e.what());
        }
    }
    // 创建下一个定时器任务，形成循环
    series_of(task)->push_back(WFTaskFactory::create_timer_task(7, 0, heartbeat_callback));
}  


// FileService 的 gRPC 实现
class FileServiceImpl final : public FileService::Service {
public:
    grpc::Status QueryFiles(grpc::ServerContext* context, const FileQueryRequest* request, FileQueryResponse* response) override {
        // 服务不再关心token，直接使用由网关验证过的user_id
        int user_id = request->user_id();
        auto files_from_db = FileDao::getFilesByUser(user_id, request->limit());

        response->set_code(0);
        response->set_message("Success");
        for (const auto& db_file : files_from_db) {
            FileInfoMessage* file_msg = response->add_files();
            file_msg->set_id(db_file.id);
            file_msg->set_file_hash(db_file.hashcode);
            file_msg->set_file_name(db_file.filename);
            file_msg->set_file_size(db_file.size);
            file_msg->set_upload_at(db_file.created_at);
        }

        return grpc::Status::OK;
    }

    grpc::Status DeleteFile(grpc::ServerContext* context, const DeleteFileRequest* request, DeleteFileResponse* response) override {
        int user_id = request->user_id();
        int file_id = request->file_id();

        if (user_id <= 0 || file_id <= 0) {
            response->set_code(1);
            response->set_message("Invalid user ID or file ID.");
            return grpc::Status::OK;
        }

        if (FileDao::deleteFileByUser(file_id, user_id)) {
            response->set_code(0);
            response->set_message("File marked as deleted.");
        } else {
            response->set_code(2);
            response->set_message("Failed to delete file.");
        }

        return grpc::Status::OK;
    }
};

void RunServer() {
    std::string server_address("0.0.0.0:50052"); // 为文件服务分配一个新端口
    FileServiceImpl service_impl;

    grpc::ServerBuilder builder;
    builder.AddListeningPort(server_address, grpc::InsecureServerCredentials());
    builder.RegisterService(&service_impl);

    std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
    std::cout << "FileService listening on " << server_address << std::endl;

    // --- 使用 ppconsul 进行服务注册 ---
    try {
        static ppconsul::Consul consul(Config::CONSUL_URI);
        g_consul_agent = new ppconsul::agent::Agent(consul);
        g_consul_agent->registerService(
            ppconsul::agent::kw::id = g_service_id,
            ppconsul::agent::kw::name = "FileService",
            ppconsul::agent::kw::address = "127.0.0.1",
            ppconsul::agent::kw::port = 50052,
            ppconsul::agent::kw::check = ppconsul::agent::TtlCheck(std::chrono::seconds{15})
        );
        std::cout << "[Registry] Service 'FileService' registered to Consul." << std::endl;

        // --- 启动心跳 ---

        // 启动心跳任务，不再需要传递任何上下文
        WFTimerTask *timer = WFTaskFactory::create_timer_task(7, 0, heartbeat_callback);
        timer->start();
        std::cout << "[Heartbeat] Heartbeat started for " << g_service_id << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "[Registry] ERROR: Failed to register to Consul. Reason: " << e.what() << std::endl;
    }
    
    server->Wait();
}

int main(int argc, char** argv) {
    if (!Config::load()) { 
        std::cerr << "Fatal: Failed to load config/app.conf" << std::endl;
        return 1;
    }
    if (!DBConnection::getInstance()->connect()) { 
        std::cerr << "Fatal: Failed to connect to database" << std::endl;
        return 1;
    }
    RunServer();
    return 0;
}
